package lastRites.game.terrain;

import java.util.ArrayList;
import java.util.List;

import lastRites.entities.Player;
import lastRites.enums.Direction;
import lastRites.game.LastRites;
import lastRites.game.interfaces.Rendering;
import lastRites.game.interfaces.Updating;

import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.state.StateBasedGame;

public class World implements Updating, Rendering {
	private TerrainBlock[][]	blocks;
	private ArrayList<Player>	players;

	public World() {
		blocks = new TerrainBlock[100][100];
		for( int row = 0; row < blocks.length; row++ ) {
			for( int col = 0; col < blocks[0].length; col++ ) {
				float roll = (float)Math.random();
				if( row < 30 ) {
					blocks[row][col] = BlockMaker.createTerrariaAir( row, col );
					continue;
				}
				if( roll < 0.50 ) {
					blocks[row][col] = BlockMaker.createTerrariaDirt( row, col );
				} else if( roll < 0.85 ) {
					blocks[row][col] = BlockMaker.createTerrariaDirt( row, col );
				} else {
					blocks[row][col] = BlockMaker.createTerrariaDirt( row, col );
				}
			}
		}
	}

	@Override
	public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException {}

	@Override
	public void update(GameContainer container, StateBasedGame game, int delta) throws SlickException {}

	public TerrainBlock[][] getBlocks() {
		return blocks;
	}

	public float canMove(Direction dir, Rectangle collisionBox, float distance) {
		if( dir == Direction.NONE ) { return 0; }
		int goodToGo = -1;
		for( int i = 0; i <= distance; i++ ) {
			int minX = (int)Math.floor( ( ( collisionBox.getMinX() + dir.adjX() * i ) / LastRites.BLOCK_SIZE ) );
			int minY = (int)Math.floor( ( ( collisionBox.getMinY() + dir.adjY() * i ) / LastRites.BLOCK_SIZE ) );
			int maxX = (int)Math.floor( ( ( collisionBox.getMaxX() + dir.adjX() * i ) / LastRites.BLOCK_SIZE ) );
			int maxY = (int)Math.floor( ( ( collisionBox.getMaxY() + dir.adjY() * i ) / LastRites.BLOCK_SIZE ) );
			// find top left square, bot right square that it overlays, iterate over that set and check for impassables
			for( int row = minY; row <= maxY; row++ ) {
				for( int col = minX; col <= maxX; col++ ) {
					if( row < 0 || row >= blocks.length || col < 0 || col >= blocks[0].length ) {
						continue;
					}
					if( !blocks[row][col].getBlockType().isPassable() ) { return goodToGo; }
				}
			}
			goodToGo++;
			// This takes care of distances that're less than 1 or decimals
			if( i + 1 > distance && i + 1 - distance > 0 ) {
				minX = (int)Math.floor( ( ( collisionBox.getMinX() + dir.adjX() * distance ) / LastRites.BLOCK_SIZE ) );
				minY = (int)Math.floor( ( ( collisionBox.getMinY() + dir.adjY() * distance ) / LastRites.BLOCK_SIZE ) );
				maxX = (int)Math.floor( ( ( collisionBox.getMaxX() + dir.adjX() * distance ) / LastRites.BLOCK_SIZE ) );
				maxY = (int)Math.floor( ( ( collisionBox.getMaxY() + dir.adjY() * distance ) / LastRites.BLOCK_SIZE ) );
				// find top left square, bot right square that it overlays, iterate over that set and check for impassables
				for( int row = minY; row <= maxY; row++ ) {
					for( int col = minX; col <= maxX; col++ ) {
						if( row < 0 || row >= blocks.length || col < 0 || col >= blocks[0].length ) { return distance; }
						if( !blocks[row][col].getBlockType().isPassable() ) { return goodToGo; }
					}
				}
				return distance;
			}
		}
		return distance;
	}

	public ArrayList<Player> getPlayers() {
		return players;
	}

	public void setPlayers(ArrayList<Player> players) {
		this.players = players;
	}

	public void addPlayer(Player player) {
		players.add( player );
	}

	public void addPlayers(List<Player> players) {
		players.addAll( players );
	}

	public void removePlayer(Player player) {
		players.remove( player );
	}

	public void removePlayers(List<Player> players) {
		players.removeAll( players );
	}

	public void removeAllPlayers() {
		players.clear();
	}
}
